
package hmm;

/**
 * Forward HMM algorithm 
 */
public class Hmm {

	/**
	 * HMM constructor
	 * @param model the Markovian model
	 */
	public Hmm(MarkovModel model) {
		this.model = model;
		hmmProccess = new double[model.getN()][2];
	}
	
	/**
	 * Run the forward algorithm, calculates the probability that
	 * the observation has occurred under the given model.
	 * @return the probability
	 */
	public double forwardAlgorithm() {
		frwdInitStates();
		int lastCol = frwdIterations();
		double p = 0.0;
		int statesNum = model.getN();
		for(int i = 0; i < statesNum; i++) {
			p += hmmProccess[i][lastCol];
		}
		return p;
	}
	
	/*
	 * Initiates the probability to start in each state
	 */
	private void frwdInitStates() {
		int N = model.getN();
		int resCol = 0; // i % 2
		double[] pi = model.getPi();
		for(int state = 0; state < N; state++) {
			hmmProccess[state][resCol] = pi[state];
		}
	}
	
	/*
	 * calculates the iterative steps of the calculation.
	 * return the most updated column.
	 */
	private int frwdIterations() {
		int oLength = model.getT();
		int statesNum = model.getN();
		MarkovianProbabilities pr = model.getPr();
		int currCol = 0; // the current column of the two, which the results will be written to
		int prevCol = 0; // the previous column in which the results from the last run saved.
		// the for starting the second column.
		for(int i = 0; i < oLength; i++) {
			prevCol = currCol;
			currCol = 1 - currCol; // change 1 to 0 and vice versa.
			int oldI = i - 1;
			for(int j = 0; j < statesNum; j++) {
				double temp = 0.0;
				for(int k = 0; k < statesNum; k++) {
					temp += hmmProccess[k][prevCol] * pr.transitionProb(j, k, oldI) * pr.observationProb(j, i);
				}
				hmmProccess[j][currCol] = temp;
			}
		}
		return currCol;
	}
	
	private MarkovModel model; // the markov model
	private double[][] hmmProccess; // the matrix with the partial results of the HMM process,
	// holds only the current column and the previous one (i.e. stages i and i+1).
}
